查看原文
其他

Android FCM 推送详解,出海应用必备

互金出海百晓通 郭霖
2024-07-19



/   今日科技快讯   /


近日,据美团数据,端午假期全国日均生活服务线上消费规模同比2019年增长达69%,广东、江苏、浙江、北京、上海、四川、山东、湖北、河南、湖南为全国消费规模TOP10省及直辖市。


/   作者简介   /


大家周二好,度过了短暂的端午节,新的一周好好加油吧!


本篇文章来自互金出海百晓通的投稿,文章主要分享了Firebase FCM推送流程详解,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。


互金出海百晓通的文章地址:

https://mp.weixin.qq.com/s/6-ULwef_M6iJZk_u4sXAwA


/   浅谈Push推送服务   /


我相信每一个App都有Push功能,他是一个免费且对App营销非常重要的一个功能。无论是电商的促销活动,还是社交软件的通知,亦或是其他具有时效性的提醒都离不开Push通知。国内的Push推送百花齐放,但如果我们是在国外开展业务,则可以通过Google的Firebase框架中的Could Message(0成本且最稳定)解决这个问题。本文将主要介绍Firebase Could Message(FCM)的集成步骤及注意点。


/   Google FCM框架概览   /


所谓Push通知,简言之就是从一个地方将消息通过网络发送到移动客户端,再由移动客户端处理展示给用户的过程。这里一共有三个角色:消息的发送方、消息接收方和消息本身。但真要实现起来也没有那么容易,例如消息的格式、发送的时机、投递的顺序、触达率等问题都需要我们关心,处理。Google FCM框架的出现就是为了解决这些问题,这样我们就可以将更多的注意力放置于消息本身。整体上看,FCM框架的整体工作流程如下:



我们按照事件流的处理从左往右看:


第一部分:消息的构建。消息的构建有两种方式:


  • Firebase控制台(Notifications Console GUI)

  • FCM Admin SDK:服务端接入 FCM Admin SDK后按照一定规则构建通知消息,此种更加灵活,方便我们根据不同用户画像做不同的App营销处理。本篇篇幅有限不做过多讨论。


第二部分:FCM BackEnd(FCM 后端),由Google负责,对已构建消息的分流处理,根据不同目标发送至不同平台用户。


第三部分:平台层,也就是我们Android 设备,这里更多指的是Android设备上的Google服务,完成最原始消息的接收。也就是说,只有有Google服务的手机才能收到FCM推送。


第四部分:FCM SDK,进一步对消息进行处理,确定分发策略,最终会发送(回调)给接入了FCM SDK的目标App。


当我们接入FCM时,只需关心第一、四部分即可。Google大大简化了我们的使用过程,在此感谢!


/   FCM 框架接入   /


这里我们选择使用Firebase FCM 控制台发送push通知(可以先忽视掉后端,我们调通后直接对接后端即可,无需做任何修改),我们集成FCM框架只需要关心两方面:


  • Firebase控制台的设置

  • 准备接入FCM SDK的Android项目


其实本质上就是之前提到的消息的发送方和接收方建立链接的过程,一旦链接建立后,便可以直接利用这个链接发送push通知。


Firebase控制台的设置


Firebase控制台的设置步骤如下:


使用Gmail登录至Firebase首页 Firebase 控制台 (google.com),点击顶部“➕”新建一个项目。



然后就会来到这个页面,这里需要设置项目名称,如果是公司已上线项目可以取App名称,这里我们演示用,直接取名FirebaseDemo,项目名称确定后,点击下一步。



第二步主要是确定是否开启Firebase的分析服务,默认开启,这里我们重点在fcm的集成上,所以先关闭。无论开启还是关闭,都不会影响到fcm功能。设置完成后直接点击“创建项目”,短时间的等待后,将会提示项目已就绪,这时候项目就创建好了。点击继续回到首页即可。



创建Android应用


一个Firebase项目是可以包含多个应用的,最简单来说,可以包含 android 和 iOS两个平台的同名称应用。来到Firebase项目首页,我们点击Android图标创建一个Android应用:



如果当前Firebase项目已经有其他应用,则可以通过继续点击“➕”或左侧齿轮进入项目设置添加新的应用。之后便会进入到如下界面:



包名就填我们App包名即可,签名证书选填可以先不管,填写完成后点击注册应用,Firebase会进行包名校验,校验通过后来到第二步:



这里会生成一个 google-services.json 的文件,其中包含了API 密钥、项目 ID、应用 ID等诸多信息,通过这些信息就可以唯一标识一个Android应用了。


按照指示将google-services.json文件添加到项目的制定目录下:



Android项目集成


对于FCM SDK的接入,对Android的项目有如下要求:


  • Android最低版本大于等于Android4.4

  • 安装有Google服务

  • 使用 Jetpack (AndroidX),这需要满足以下版本要求:
    com.android.tools.build:gradle 3.2.1 或更高版本
    compileSdkVersion 28 或更高版本


添加依赖FCM SDK依赖


这里有两种方式:


  • 通过Firebase Android BoM

  • 单独引入FCM SDK


因为Firebase SDK集合除了FCM还有很多其他比较有用的SDK,如果需要同时引入这些SDK,难免会有一些依赖版本冲突的情况发生,所以更推荐使用Firebase Android BoM的方式引入,只需要指定目标BoM版本,后续只需按需引入其他Firebase SDK即可,这样可以保证所有引入的库的版本是兼容的。


通过Firebase BoM引入FCM


在模块(应用级)的build.gradle配置文件中引入依赖即可:


dependencies {

    implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    api 'com.google.firebase:firebase-messaging'

    // ... 省略其他无关代码
    // 如果后续需要引入 firebase-analytics ,只需添加如下代码即可,无需考虑 firebase-messaging 和 firebase-analytics 之间的版本兼容问题
    // implementation 'com.google.firebase:firebase-analytics'
}


集成google-services插件


FCM SDK有两种初始化方式:


  • 代码显示调用初始化

  • 通过google-service自动初始化


这里我们选择引入google-services插件的方式,这样一方面在编译期gradle可以自动读取google-services.json中的内容,可以很大程度上减少了手动编码出错的可能。


另一方面,我们也无需在应用启动时,手动的编写初始化代码,让业务代码更加简洁。初始化步骤如下:


1.在项目级别 build.gradle 文件中引入 google-services 插件:


buildscript {
    repositories {
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
        maven { url "https://dl.google.com/dl/android/maven2" }
        mavenCentral()
        google()
    }
    dependencies {
        // 引入 google-service插件
        classpath 'com.google.gms:google-services:4.3.15'
        // ...省略无关代码
    }
}

allprojects {
    repositories {
        mavenCentral()
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
        maven { url "https://dl.google.com/dl/android/maven2" }
        maven { url 'https://jitpack.io' }
        google()
    }
}


2.在应用级目录下的build.gradle文件中应用插件(应用级目录):


plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'com.google.gms.google-services' // 应用 google-service插件
}


至此,Firebase控制台和FCM SDK的引入就都完成了。


开始发送push消息


消息主要有以下3个注意点:


  • 消息的分类

  • 消息的接收(Android 设备/客户端)

  • 消息的发送(Firebase控制台)


消息的分类


Fcm将Push消息按照用途分为了两种:



通知消息和数据消息都属于Fcm Push消息,那么Fcm是如何区分的呢?这就要从Push消息的格式来看。无论是通知消息还是数据消息都是以Json数据格式组织的,无非就是关键字段的Key不同罢了。


如果是通知消息,消息中将包含一个"notification"字段:


{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"标题",
      "body":"我是内容!"
    }
  }
}


之前有提到,Push消息会经由Fcm SDK传递到我们的客户端,这里当Fcm SDK检测到消息中包含”notification“字段时,就会将其当做一个通知消息来处理。


而数据消息所谓的由客户端自行处理,也仍然经过Fcm SDK,只不过 Fcm SDK并不会对其进行任何处理,只是直接投递到客户端罢了。对应的,数据消息的识别字段是”data“。实例数据如下:


{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "内容",
    }
  }
}


如上所见,Fcm SDK 是通过识别关键字段来进行消息的分类处理,所以上述的”notification“,“data”都是fcm识别的关键字之一,定义数据消息时就需要特别注意,按需设置关键字段。同时如果要明确发送数据消息(非通知消息)还需要避开“from”、“message_type”或以“google”或“gcm”开头的任何字词。


无论是通知消息还是数据消息都包含了一个token字段,这个字段是由Fcm SDK生成用于标识当前客户端的,客户端可以将这个值保存下来并上报给服务端,这样后续服务端就可以通过指定token字段的值,定向向指定客户端发送消息了,做到精准营销用户。


不过token的值会如下情况下发生改变,例如:


  • 在其他设备上重新登陆

  • 用户卸载/重新安装应用

  • 用户清除应用数据。


这里不做过多关心,这并不会影响到什么。


消息的处理


在初始设置阶段,我们完成了客户端FCM SDK的接入,如果想要顺利收到Push消息还需要完成如下设置:


1.扩展 FirebaseMessagingService 并在AndroidMainFest.XML中声明:


<service
    android:name=".java.MyService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>


2.token的保存和消息的接收


class MyService : FirebaseMessagingService() {

    // 一旦token有变化,onNewToken方法就会被回调
    override fun onNewToken(token: String) {
        super.onNewToken(token)
        Log.e(TAG, "new token $token")
    }

    override fun onMessageReceived(message: RemoteMessage) {
        super.onMessageReceived(message)
        Log.e(TAG,"onMessageReceived : ${message.messageType}")
    }

    override fun onDeletedMessages() {
        super.onDeletedMessages()
        Log.e(TAG,"onDeletedMessages ")
    }
}


扩展 FirebaseMessagingService 后,有三个方法可以重写:


  1. onNewToken:每次有新token生成时回调,我们可以利用这个机制保存token

  2. onMessageReceived:

    1. 对于通知消息:如果App在前台并收到消息时,这个方法就会回调。RemoteMessage的数据结构和之前提到的Json一一对应,这就不展开了。若果App处于后台,消息则会直接展示在通知栏(需通知权限)

    2. 对于数据消息:无论App处于前台还是后台,都会回调到这个方法

    3. 参数RemoteMessage中的 Notification 类型的notification对象,用于承载通知消息的数据

  3. onDeletedMessages : Push消息被删除时回调


至此,我们的客户端就做好了接收消息的准备。但是此时App只能在设备解锁的前提下收到消息,如果想要在解锁前收到消息,还需要完成如下设置:


添加 firebase-messaging-directboot 依赖


/ 如果是Firebase BoM方式依赖
implementation 'com.google.firebase: firebase-messaging-directboot'
// 否则
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'


给Service添加directBootAware属性


<service
    android:name=".MyService"
    android:exported="false"
    android:directBootAware="true">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>


通知权限


如果需要在通知栏展示Push消息,对于Android 13及以上设备需要显示申请通知权限


<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />


代码动态申请权限:


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(this, "android.permission.POST_NOTIFICATIONS") ==
        PackageManager.PERMISSION_GRANTED
    ) {
    }  else {

    }
}


消息的发送


当客户端做好接收消息的准备后,就可以通过Firebase控制台创建一个Push消息测试一下了,在Firebase控制面板左侧Tab列表中找到Messaing选项



如果是第一次创建Push消息,则会来到如下界面,这里选择“创建首个宣传活动”(需要当前Firebase登录账户拥有当前项目的所有者或修改者权限)。



之后会弹起如下弹窗,选择“Firebase通知消息”。



选择“Firebase通知消息”之后,便可以进入Push消息的具体设置界面了,这里我们随便设置一个标题和通知内容。



再正式发布前,可以点击右侧的发送测试消息进行测试:



这里需要添加一个“FCM注册令牌”,还记得我们上文提到token吗,填写到这里就可以了(如果之前忘记保存了,可以通过清除缓存并重启App得到)。

添加完成后,在App测添加打印token:


override fun onMessageReceived(message: RemoteMessage) {
        super.onMessageReceived(message)
        Log.e(TAG, "Title :${message.notification?.title.orEmpty()}")
        Log.e(TAG, "Body :${message.notification?.body}")
    }


然后我们将App切换到前台,点击测试,onMessageReceived就会被回到如下:



将App切换到后台后,再次点击测试,可以看到通知栏有通知收到。



但是因为我们没做设置,所以通知展示了默认图标和颜色,这里可以自定义通知图标:


// AndroidmainFest.xml 中
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />

<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />


至此,整体流程完成,Yes!!!


github地址(欢迎下载体验):

https://github.com/loveAndroidAndroid/FirebaseDemo


推荐阅读:

我的新书,《第一行代码 第3版》已出版!

原创:写给初学者的Jetpack Compose教程,用derivedStateOf提升性能

实现录音器、音频格式转换器和播放器


欢迎关注我的公众号

学习技术或投稿



长按上图,识别图中二维码即可关注

继续滑动看下一个
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存